<?php
/**
 * Provides info checking for BRail_Application_Controller_Info
 * @name BRail_Info
 */
class BRail_Application_Info
{
    /**
     * Retrieves phpinfo() information to array
     * @return array phpinfo() array
     */
    public static function getPhpInfoAsArray()
    {
        ob_start();
        phpinfo();
        $phpinfo = array('phpinfo' => array());
        if (preg_match_all('#(?:<h2>(?:<a name=".*?">)?(.*?)(?:</a>)?</h2>)|(?:<tr(?: class=".*?")?>' .
            '<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>' .
            '(?:<t[hd](?: class=".*?")?>(.*?)\s*</t[hd]>)?)?</tr>)#s',
            ob_get_clean(),
            $matches,
            PREG_SET_ORDER)) {
            foreach ($matches as $match) {
                if (strlen($match[1])) {
                    $phpinfo[$match[1]] = array();
                } elseif (isset($match[3])) {
                    $phpinfo[end(array_keys($phpinfo))][$match[2]] =
                    isset($match[4]) ? array($match[3], $match[4]) : $match[3];
                } else {
                    $phpinfo[end(array_keys($phpinfo))][] = $match[2];
                }
            }
        }
        return $phpinfo;
    }

    /**
     * Checks if permissions are sufficient  on files/directories
     * @param int $required Required permission mask (in form 777)
     * @param int $actual Actual permission mask
     * @return bool True if permission is higher
     */
    public static function hasSufficientPermission($required, $actual)
    {
        if (
            substr($required, 0, 1) <= substr($actual, 0, 1)
            &&
            substr($required, 1, 1) <= substr($actual, 1, 1)
            &&
            substr($required, 2, 1) <= substr($actual, 2, 1)
        ) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Verify network availability
     * @param array $hosts Hosts array with services
     * @return array List of hosts with their status
     */
    public static function verifyNetwork($hosts)
    {
        $networkCheckList = array();
        if (isset($hosts) && count($hosts) > 0) {
            foreach ($hosts as $host => $serviceString) {
                $hostCheckList = array();
                $services = explode(',', $serviceString);
                foreach ($services as $service) {
                    switch (trim($service)) {
                        case 'ping':
                            $checkResult = BRail_Network_Icmp::ping($host);
                            $hostCheckList['ping'] = ($checkResult === true ? 'OK' : 'Failed');
                            break;
                        case 'http':
                            $checkResult = BRail_Network_Check::checkHttp($host);
                            $hostCheckList['http'] = ($checkResult === true ? 'OK' : $checkResult);
                            break;
                    }
                }
                $networkCheckList[] = array(
                    'name' => $host,
                    'status' => $hostCheckList
                    );
            }
        }
        return $networkCheckList;
    }

    /**
     * Retrieve SVN Information
     * @param string $path The path of the SVN repository
     * @return array|bool SVN Information or false if unsuccessfull
     */
    public static function getSvnInfo($path)
    {
        if (file_exists($path . '/.svn/entries')) {
            $entries = file($path . '/.svn/entries');
            return array(
                'revision' => $entries[3],
                'repositoryUrl' => $entries[4],
                'repositoryBaseUrl' => $entries[5],
                'lastUpdate' => $entries[9]
            );
        } else {
            return false;
        }
    }

    /**
     * Verify directory/file permissions
     * @param array $checkList List of directories/files to check, including their required permission level
     * @param bool $isDir True if checking directories, false if checking files
     * @return array List of directories/files with their status
     */
    public static function verifyPermissions($checkList, $isDir)
    {
        /**
         * We can not get user/group permissions on Windows
         */
        if (getenv('OS')) {
            $osName = getenv('OS');
        } elseif (getenv('MACHTYPE')) {
            $osName = getenv('MACHTYPE');
        } else {
            $osName = 'Unknown';
        }
        if (preg_match("/win/i", $osName)) {
            $isWindows = true;
        } else {
            $isWindows = false;
        }

        $returnList = array();
        if (count($checkList) > 0) {
            if ($isDir === true) {
                foreach ($checkList as $directory => $reqPermission) {
                    $status = 'OK';
                    if (!file_exists($directory)) {
                        $directory = ROOT_PATH . '/' . $directory;
                    }
                    if (file_exists($directory)) {
                        $dirPermission = fileperms($directory);
                        if (($dirPermission & 0x4000) != 0x4000) {
                            $status = 'Not a directory';
                        } elseif (
                            !$isWindows
                            &&
                            !self::hasSufficientPermission($reqPermission, substr(decoct($dirPermission), 2))) {
                            $status = 'Insufficient permission level - ' . $reqPermission . ' required';
                        }
                    } else {
                        $status = "Directory doesn't exist";
                    }
                    $returnList[] = array(
                        'name' => $directory,
                        'status' => $status
                    );
                }
            } else {
                foreach ($checkList as $file => $reqPermission) {
                    $status = 'OK';
                    if (!file_exists($file)) {
                        $file = ROOT_PATH . '/' . $file;
                    }
                    if (file_exists($file)) {
                        $filePermission = fileperms($file);
                        if (
                            !$isWindows
                            &&
                            !self::hasSufficientPermission($reqPermission, substr(decoct($filePermission), 2))
                            ) {
                            $status = 'Insufficient permission level - ' . $reqPermission . ' required';
                        }
                    } else {
                        $status = "File doesn't exist";
                    }
                    $returnList[] = array(
                        'name' => $file,
                        'status' => $status
                    );
                }
            }
        }
        return $returnList;
    }
}